package com.tiancheng.trade.settlement.service.order.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tiancheng.trade.commom.core.data.PageInfo;
import com.tiancheng.trade.settlement.bo.*;
import com.tiancheng.trade.settlement.enums.OrderSourceEnum;
import com.tiancheng.trade.settlement.enums.SubOrderStatusEnum;
import com.tiancheng.trade.settlement.exception.error.BusinessErrorInfoEnum;
import com.tiancheng.trade.settlement.mapper.merchant.MerchantMapper;
import com.tiancheng.trade.settlement.mapper.order.SubOrderMapper;
import com.tiancheng.trade.settlement.model.merchant.Merchant;
import com.tiancheng.trade.settlement.model.order.SubOrder;
import com.tiancheng.trade.settlement.service.order.ISubOrderService;
import com.tiancheng.trade.settlement.util.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 子订单信息
 */
@Slf4j
@Service
public class SubOrderServiceImpl implements ISubOrderService {
    @Autowired
    private SubOrderMapper subOrderMapper;
    @Autowired
    private MerchantMapper merchantMapper;

    @Override
    public List<SubOrder> findByOrderId(String orderId) {
        QueryWrapper<SubOrder> conditions = new QueryWrapper<>();
        conditions.eq("order_id", orderId);
        return subOrderMapper.selectList(conditions);
    }

    @Override
    public List<SubOrder> findBySubOrderIds(Collection<String> subOrderIds) {
        QueryWrapper<SubOrder> conditions = new QueryWrapper<>();
        conditions.in("sub_order_id", subOrderIds);
        return subOrderMapper.selectList(conditions);
    }

    @Override
    public List<SubOrder> findByOrderIdAndSubOrderIds(String orderId, List<String> subOrderIds) {
        BusinessErrorInfoEnum.QUERY_ARGS_ERROR.assertIsTrue(StringUtils.isNotEmpty(orderId) && CollectionUtils.isNotEmpty(subOrderIds));
        QueryWrapper<SubOrder> conditions = new QueryWrapper<>();
        conditions.eq("order_id", orderId);
        conditions.in("sub_order_id", subOrderIds);
        return subOrderMapper.selectList(conditions);
    }

    /**
     * 订单数据统计汇总查询
     *
     * @param year  {@link Integer} 年份
     * @param month {@link String} 月份
     * @return {@link List<ServiceAmountCountBO>}
     */
    @Override
    public List<ServiceAmountCountBO> serviceAmountCount(Integer year, String month) {
        List<ServiceAmountCountBO> results = subOrderMapper.serviceAmountCount(year, month);
        // 分转元
        if (!results.isEmpty()) {
            BigDecimal bd = new BigDecimal(100);
            BigDecimal zero = new BigDecimal("0.00");
            List<String> rSources = new ArrayList<>();
            for (ServiceAmountCountBO result : results) {
                rSources.add(result.getOrderSource());

                result.setServiceSuccessAmount(result.getServiceSuccessAmount() == null ? zero : result.getServiceSuccessAmount().divide(bd, 2, BigDecimal.ROUND_HALF_UP));
                result.setServiceIngAmount(result.getServiceIngAmount() == null ? zero : result.getServiceIngAmount().divide(bd, 2, BigDecimal.ROUND_HALF_UP));
                result.setServiceFailAmount(result.getServiceFailAmount() == null ? zero : result.getServiceFailAmount().divide(bd, 2, BigDecimal.ROUND_HALF_UP));
            }
            List<String> orderSources = Arrays.stream(OrderSourceEnum.values()).map(OrderSourceEnum::getCode).collect(Collectors.toList());
            for (Object o : org.apache.commons.collections.CollectionUtils.subtract(orderSources, rSources)) {
                results.add(new ServiceAmountCountBO() {{
                    setOrderSource(o + "");
                    setServiceSuccessAmount(zero);
                    setServiceIngAmount(zero);
                    setServiceFailAmount(zero);
                }});
            }
            results.forEach(d -> d.setOrderSourceName(OrderSourceEnum.getDesc(d.getOrderSource())));
        }
        return results;
    }

    /**
     * 订单数据明细统计查询
     *
     * @param requestBO {@link ServiceDetailCountRequestBO}
     * @return {@link List<ServiceDetailCountResBO>}
     */
    @Override
    public PageInfo<ServiceDetailCountResBO> serviceDetailCountPage(ServiceDetailCountRequestBO requestBO) {
        PageInfo<ServiceDetailCountResBO> pageInfo = new PageInfo<>();

        Set<String> merchantCodes = new HashSet<>();
        if (StringUtils.isNotBlank(requestBO.getOrganizationCode())) {
            List<Merchant> merchants = merchantMapper.selectList(new QueryWrapper<Merchant>() {{
                eq("organization_code", requestBO.getOrganizationCode());
                eq("state", 1);
                eq("is_delete", 0);
            }});
            if (!merchants.isEmpty()) {
                merchantCodes = merchants.stream().map(Merchant::getMerchantCode).collect(Collectors.toSet());
            }
        }
        Long count = subOrderMapper.serviceDetailCountCount(requestBO, merchantCodes);
        if (null == count || count < 1) {
            return pageInfo;
        }
        List<ServiceDetailCountResBO> resBOS = subOrderMapper.serviceDetailCount(requestBO, merchantCodes);
        if (!resBOS.isEmpty()) {
            merchantCodes.clear();
            BigDecimal bdd = new BigDecimal(100);
            for (ServiceDetailCountResBO resBO : resBOS) {
                if (null != requestBO.getYear()) {
                    resBO.setCycleName(requestBO.getYear() + "年");
                } else {
                    String[] arrStart = requestBO.getDayCycleStart().substring(0, 10).split("-");
                    String[] arrEnd = requestBO.getDayCycleEnd().substring(0, 10).split("-");
                    resBO.setCycleName(arrStart[0] + "年" + arrStart[1] + "月" + arrStart[2] + "日" + "-"
                            + arrEnd[0] + "年" + arrEnd[1] + "月" + arrEnd[2] + "日");
                }
                resBO.setServiceName(SubOrderStatusEnum.getDesc(resBO.getServiceName()));
                resBO.setOrderSourceName(OrderSourceEnum.getDesc(resBO.getOrderSourceName()));
                resBO.setOrderAmount(resBO.getOrderAmount().divide(bdd, 2, BigDecimal.ROUND_HALF_UP));
                resBO.setDiscountAmount(resBO.getDiscountAmount().divide(bdd, 2, BigDecimal.ROUND_HALF_UP));
                resBO.setCostAmount(resBO.getCostAmount().divide(bdd, 2, BigDecimal.ROUND_HALF_UP));

                merchantCodes.add(resBO.getMerchantName());
            }
            if (!merchantCodes.isEmpty()) {
                Map<String, MerchantQueryBo> map = merchantMapper.findByMerchantCods(merchantCodes).stream().collect(Collectors.toMap((MerchantQueryBo::getMerchantCode), Function.identity()));
                resBOS.forEach(d -> {
                    d.setOrganizationName(map.get(d.getMerchantName()) == null ? "" : map.get(d.getMerchantName()).getOrganizationName());
                    d.setMerchantName(map.get(d.getMerchantName()) == null ? "" : map.get(d.getMerchantName()).getMerchantName());
                });
            }
        }
        pageInfo = new PageInfo<>(resBOS, new PageInfo.Pagination(requestBO.getCurrentPage(), requestBO.getPageSize(), count));
        return pageInfo;
    }

    /**
     * 订单数据明细统计导出
     *
     * @param exportBO {@link ServiceDetailCountExportBO}
     * @param request  {@link HttpServletRequest}
     * @param response {@link HttpServletResponse}
     */
    @Override
    public void serviceDetailCountExport(ServiceDetailCountExportBO exportBO, HttpServletRequest request,
                                         HttpServletResponse response) throws Exception {
        try {
            String fileName = "订单数据明细第" + exportBO.getStart() + "-" + exportBO.getEnd() + "条";

            String[] title = new String[]{"统计周期", "订单状态", "场景", "组织机构", "商户名称", "产品名称", "销售金额(元)", "优惠金额(元),", "结算金额(元)", "笔数"};

            Set<String> merchantCodes = new HashSet<>();
            if (StringUtils.isNotBlank(exportBO.getOrganizationCode())) {
                List<Merchant> merchants = merchantMapper.selectList(new QueryWrapper<Merchant>() {{
                    eq("organization_code", exportBO.getOrganizationCode());
                    eq("state", 1);
                    eq("is_delete", 0);
                }});
                if (!merchants.isEmpty()) {
                    merchantCodes = merchants.stream().map(Merchant::getMerchantCode).collect(Collectors.toSet());
                }
            }
            Long count = subOrderMapper.serviceDetailCountCount(exportBO, merchantCodes);
            if (count < 0) {
                ExcelUtil.exportExcle(request, response, new XSSFWorkbook(), fileName);
            }
            List<ServiceDetailCountResBO> resBOS = subOrderMapper.serviceDetailCountExport(exportBO, merchantCodes);
            if (resBOS.isEmpty()) {
                ExcelUtil.exportExcle(request, response, new XSSFWorkbook(), fileName);
            }

            merchantCodes.clear();
            merchantCodes = resBOS.stream().map(ServiceDetailCountResBO::getMerchantName).collect(Collectors.toSet());
            Map<String, MerchantQueryBo> map = merchantMapper.findByMerchantCods(merchantCodes).stream().collect(Collectors.toMap((MerchantQueryBo::getMerchantCode), Function.identity()));
            List<Map<String, Object>> dataList = new ArrayList<>();
            BigDecimal bdd = new BigDecimal(100);
            for (ServiceDetailCountResBO resBO : resBOS) {
                dataList.add(new LinkedHashMap<String, Object>(){{
                    String cycle;
                    if (null != exportBO.getYear()) {
                        cycle = exportBO.getYear() + "年";
                    } else {
                        String[] arrStart = exportBO.getDayCycleStart().substring(0, 10).split("-");
                        String[] arrEnd = exportBO.getDayCycleEnd().substring(0, 10).split("-");
                        cycle = arrStart[0] + "年" + arrStart[1] + "月" + arrStart[2] + "日" + "-" +
                                arrEnd[0] + "年" + arrEnd[1] + "月" + arrEnd[2] + "日";
                    }
                    put("cycle", cycle);
                    put("serviceName", SubOrderStatusEnum.getDesc(resBO.getServiceName()));
                    put("orderSourceName", OrderSourceEnum.getDesc(resBO.getOrderSourceName()));
                    put("organizationName", map.get(resBO.getMerchantName()) == null ? "" : map.get(resBO.getMerchantName()).getOrganizationName());
                    put("merchantName", map.get(resBO.getMerchantName()) == null ? "" : map.get(resBO.getMerchantName()).getMerchantName());
                    put("productName", resBO.getProductName());
                    put("orderAmount", resBO.getOrderAmount().divide(bdd, 2, BigDecimal.ROUND_HALF_UP));
                    put("discountAmount", resBO.getDiscountAmount().divide(bdd, 2, BigDecimal.ROUND_HALF_UP));
                    put("costAmount", resBO.getCostAmount().divide(bdd, 2, BigDecimal.ROUND_HALF_UP));
                    put("count", resBO.getCount());
                }});
            }

            Workbook workbook = ExcelUtil.buildWorkbook(fileName, title, dataList);
            ExcelUtil.exportExcle(request, response, workbook, fileName);
        } catch (Exception e) {
            log.error("订单数据明细统计导出失败：{}", e.getMessage());
            throw new Exception("订单数据明细统计导出失败", e);
        }
    }
}
